Skip to content

Conversation

philnik777
Copy link
Contributor

@philnik777 philnik777 commented Oct 7, 2025

__string_is_trivial_iterator_v already implies that the iterator is contiguous. There is no need to specialize for input ranges specifically.

Copy link

github-actions bot commented Oct 7, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@philnik777 philnik777 force-pushed the string_simplify_append_assign branch 2 times, most recently from f0148e8 to a54925e Compare October 8, 2025 08:34
@ldionne ldionne marked this pull request as ready for review October 8, 2025 15:24
@ldionne ldionne requested a review from a team as a code owner October 8, 2025 15:24
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Oct 8, 2025
@llvmbot
Copy link
Member

llvmbot commented Oct 8, 2025

@llvm/pr-subscribers-libcxx

Author: Nikolas Klauser (philnik777)

Changes

__string_is_trivial_iterator_v already implies that the iterator is contiguous. There is no need to specialize for input ranges specifically.


Full diff: https://github.com/llvm/llvm-project/pull/162254.diff

1 Files Affected:

  • (modified) libcxx/include/string (+6-22)
diff --git a/libcxx/include/string b/libcxx/include/string
index 363f27a51648c..5e10aa4671621 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -1413,24 +1413,16 @@ public:
   _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s);
   _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(size_type __n, value_type __c);
 
-  template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0>
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
-  append(_InputIterator __first, _InputIterator __last) {
-    const basic_string __temp(__first, __last, __alloc_);
-    append(__temp.data(), __temp.size());
-    return *this;
-  }
-
-  template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0>
+  template <class _InputIterator>
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
-  append(_ForwardIterator __first, _ForwardIterator __last) {
+  append(_InputIterator __first, _InputIterator __last) {
     size_type __sz  = size();
     size_type __cap = capacity();
     size_type __n   = static_cast<size_type>(std::distance(__first, __last));
     if (__n == 0)
       return *this;
 
-    if (__string_is_trivial_iterator_v<_ForwardIterator> && !__addr_in_range(*__first)) {
+    if (__string_is_trivial_iterator_v<_InputIterator> && !__addr_in_range(*__first)) {
       if (__cap - __sz < __n)
         __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0);
       __annotate_increase(__n);
@@ -1540,17 +1532,10 @@ public:
   _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s);
   _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(size_type __n, value_type __c);
 
-  template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0>
+  template <class _InputIterator>
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
   assign(_InputIterator __first, _InputIterator __last) {
-    __assign_with_sentinel(__first, __last);
-    return *this;
-  }
-
-  template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0>
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
-  assign(_ForwardIterator __first, _ForwardIterator __last) {
-    if (__string_is_trivial_iterator_v<_ForwardIterator>) {
+    if _LIBCPP_CONSTEXPR (__string_is_trivial_iterator_v<_InputIterator>) {
       size_type __n = static_cast<size_type>(std::distance(__first, __last));
       __assign_trivial(__first, __last, __n);
     } else {
@@ -1563,8 +1548,7 @@ public:
 #  if _LIBCPP_STD_VER >= 23
   template <_ContainerCompatibleRange<_CharT> _Range>
   _LIBCPP_HIDE_FROM_ABI constexpr basic_string& assign_range(_Range&& __range) {
-    if constexpr (__string_is_trivial_iterator_v<ranges::iterator_t<_Range>> &&
-                  (ranges::forward_range<_Range> || ranges::sized_range<_Range>)) {
+    if constexpr (__string_is_trivial_iterator_v<ranges::iterator_t<_Range>>) {
       size_type __n = static_cast<size_type>(ranges::distance(__range));
       __assign_trivial(ranges::begin(__range), ranges::end(__range), __n);
 

Comment on lines 1427 to 1430
__grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0);
__annotate_increase(__n);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this could be something like

string __tmp;
__tmp.reserve(__sz + __n);
__tmp.assign(begin(), end());
__tmp.insert(__tmp.end(), __first, __last);
swap(*this, __tmp);

And then we don't have to care about __addr_in_range(*__first) anymore. That's basically the algorithm that we do in vector as well.

This can be done in a follow-up patch.

@philnik777 philnik777 force-pushed the string_simplify_append_assign branch from a54925e to 583d424 Compare October 9, 2025 08:54
@philnik777 philnik777 force-pushed the string_simplify_append_assign branch from 583d424 to f064ac2 Compare October 9, 2025 11:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants